use std::{collections::HashSet, path::PathBuf};

use crate::error::FileStoreError;

mod records;
pub mod rocksdb;

pub use records::*;

// Store trait 的方法返回 impl Iterator 而非 Vec 的设计选择，主要涉及性能、内存使用和 API 灵活性的权衡。以下是具体分析：
// 优点：
// 内存效率更高
// impl Iterator 表示返回的是一个惰性计算的迭代器，元素是按需生成的，不需要一次性将所有数据加载到内存中（如 Vec 会预先分配内存存储所有元素）。对于可能包含大量记录的存储操作（如 fetch_all_published_files），这种设计可以显著减少内存占用，避免因数据量过大导致的内存峰值问题。

// 避免不必要的计算
// 如果调用者只需要遍历部分元素（例如通过 take(n) 提前终止），迭代器可以提前停止计算，而 Vec 必须预先收集所有元素（即使后续不需要），浪费计算资源。

// API 灵活性更强
// 迭代器天然支持链式操作（如 map、filter、fold 等），调用者可以直接在迭代器上组合操作，无需额外转换。例如：

// rust
// let records = store.fetch_all_published_files()?;
// let valid_records = records.filter(|r| r.is_valid()); // 直接在迭代器上过滤
//
// 劣势：
// 生命周期管理更复杂
// 迭代器可能依赖方法内部的临时数据或对 self 的引用（如数据库游标），需要确保迭代器的生命周期不超过这些数据的生命周期。在 trait 中使用 impl Iterator 时，可能需要显式声明生命周期参数（如 fn fetch_all(...) -> impl Iterator<Item = T> + 'a），否则可能限制实现的灵活性（例如无法返回依赖 self 引用的迭代器）。

// 不支持随机访问或多次遍历
// 迭代器通常是“一次性”的（除非实现了 Clone 或双端特性），无法像 Vec 那样通过索引随机访问元素，也无法多次遍历（需重新获取迭代器）。如果调用者需要多次遍历或按索引访问数据，Vec 会更方便。

// 实现约束更严格
// trait 的实现者必须提供一个具体的迭代器类型（如数据库查询的游标、文件读取的行迭代器等），而返回 Vec 只需将数据收集到动态数组中即可，实现成本更低（尤其对于简单场景）。

// 总结
// impl Iterator 更适合数据量大、需惰性计算或流式处理的场景（如文件存储的批量读取），能有效降低内存和计算开销；而 Vec 更适合数据量小、需多次访问或随机访问的场景（如需要频繁遍历或修改的小规模数据）。当前 Store trait 的设计更倾向于性能优化，符合存储层对资源高效利用的需求。

pub trait Store {
    // Published file operations
    fn add_published_file_record(&self, record: PublishedFileRecord) -> Result<(), FileStoreError>;
    fn published_file_exists(&self, file_id: u64) -> Result<bool, FileStoreError>;
    fn published_file_metadata_path(&self, file_id: u64) -> Result<PathBuf, FileStoreError>;
    fn published_file_chunks_dir(&self, file_id: u64) -> Result<PathBuf, FileStoreError>;
    fn fetch_published_file_chunk_path(
        &self,
        file_id: u64,
        chunk_id: usize,
    ) -> Result<Option<PathBuf>, FileStoreError>;
    fn fetch_all_published_files(
        &self,
    ) -> Result<impl Iterator<Item = PublishedFileRecord> + Send + Sync, FileStoreError>;

    fn fetch_all_public_published_files(
        &self,
    ) -> Result<impl Iterator<Item = PublishedFileRecord> + Send + Sync, FileStoreError>;

    // Pending download operations
    fn add_pending_download(&self, record: PendingDownloadRecord) -> Result<(), FileStoreError>;
    fn remove_pending_download(&self, file_id: u64) -> Result<(), FileStoreError>;
    fn fetch_all_pending_downloads(
        &self,
    ) -> Result<impl Iterator<Item = PendingDownloadRecord> + Send, FileStoreError>;
    fn add_downloaded_chunk_to_pending_download(
        &self,
        file_id: u64,
        chunk_id: usize,
    ) -> Result<(), FileStoreError>;
    fn already_downloaded_chunks_in_pending_download(
        &self,
        file_id: u64,
    ) -> Result<HashSet<usize>, FileStoreError>;
    fn check_downloaded_chunks_in_pending_download(
        &self,
        file_id: u64,
        chunk_id: usize,
    ) -> Result<bool, FileStoreError>;
    fn fetch_pending_downloaded_chunk_path(
        &self,
        file_id: u64,
        chunk_id: usize,
    ) -> Result<Option<PathBuf>, FileStoreError>;
}
